home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / forth / pfe-0.000 / pfe-0 / pfe-0.9.13 / src / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-17  |  13.0 KB  |  470 lines

  1. /*
  2.  * This file is part of the portable Forth environment written in ANSI C.
  3.  * Copyright (C) 1995  Dirk Uwe Zoller
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Library General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13.  * See the GNU Library General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Library General Public
  16.  * License along with this library; if not, write to the Free
  17.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  * This file is version 0.9.13 of 17-July-95
  20.  * Check for the latest version of this package via anonymous ftp at
  21.  *    roxi.rz.fht-mannheim.de:/pub/languages/forth/pfe-VERSION.tar.gz
  22.  * or    sunsite.unc.edu:/pub/languages/forth/pfe-VERSION.tar.gz
  23.  * or    ftp.cygnus.com:/pub/forth/pfe-VERSION.tar.gz
  24.  *
  25.  * Please direct any comments via internet to
  26.  *    duz@roxi.rz.fht-mannheim.de.
  27.  * Thank You.
  28.  */
  29. /*
  30.  * main.c --- Process command line, get memory and start up.
  31.  * (duz 15Jul93)
  32.  */
  33.  
  34. #include "forth.h"
  35. #include "support.h"
  36. #include "term.h"
  37. #include "lined.h"
  38. #include "help.h"
  39.  
  40. #include <stdlib.h>
  41. #include <stdarg.h>
  42. #include <string.h>
  43. #include <float.h>
  44. #ifdef HAVE_LOCALE_H
  45. #include <locale.h>
  46. #endif
  47.  
  48. #include "nonansi.h"
  49. #include "missing.h"
  50.  
  51. /************************************************************************/
  52. /* physical instances of global system variables:                       */
  53. /************************************************************************/
  54. /* *INDENT-OFF* */
  55. #ifndef REGIP
  56. Xt *    ip;            /* the instruction pointer */
  57. #endif
  58.  
  59. #ifndef REGSP
  60. Cell *    sp;            /* the stack pointer */
  61. #endif
  62.  
  63. #ifndef REGRP
  64. Xt **    rp;            /* the return stack pointer */
  65. #endif
  66.  
  67. #if !defined W && !defined REGW
  68. Xt    W;            /* used inside the inner interpreter */
  69. #endif
  70.  
  71. #ifndef REGLP
  72. Cell *    lp;            /* pointer to local variables */
  73. #endif
  74.  
  75. #ifndef REGFP
  76. double *fp;            /* the floating point stack pointer */
  77. #endif
  78. /* *INDENT-ON* */
  79.  
  80. struct memory membot;        /* start of each area */
  81. struct memory memtop;        /* end of each area */
  82. struct memsiz memsiz;        /* size of each area in cells */
  83. struct sysvar sys;        /* all other FORTH variables */
  84.  
  85. char host_system[] = HOST_SYSTEM;
  86. int _argc;            /* exported command line options */
  87. char **_argv;
  88. int app_argc;            /* exported application cmdline options */
  89. char **app_argv;
  90. int exitcode = 0;
  91.  
  92. /* very simple error handling for fatal errors */
  93.  
  94. void
  95. fatal (const char *msg,...)
  96. {
  97.   char buf[128];
  98.   va_list p;
  99.  
  100.   va_start (p, msg);
  101.   vsprintf (buf, msg, p);
  102.   fprintf (stderr, "\n%s: %s (fatal)\n", (char *) _argv[0], buf);
  103.   eXit (2);
  104. }
  105.  
  106. /************************************************************************/
  107. /* Analyze command line options:                                        */
  108. /************************************************************************/
  109.  
  110. struct options option =        /* initialized with defaults */
  111. {
  112.   CAPS_ON,            /* caps_on */
  113.   LOWER_CASE_ON,        /* lower_case_on */
  114.   LWRCASE_FN_ON,        /* lower_case_fn */
  115.   FLOAT_INPUT_ON,        /* float_input */
  116.   0,                /* license */
  117.   0,                /* warranty */
  118.   0,                /* quiet */
  119.   0,                /* verbose */
  120.   0,                /* canonical */
  121.   0,                /* stdio */
  122.   0,                /* debug */
  123.  
  124.   TEXT_COLS,            /* cols */
  125.   TEXT_ROWS,            /* rows */
  126.  
  127.   TOTAL_SIZE,            /* total_size of system in bytes */
  128.  
  129. #if defined HPUX68K && !defined __GNUC__
  130.   (TOTAL_SIZE / 8) / CELLSIZE,
  131.   (TOTAL_SIZE / 16) / DFLOATSIZE,
  132.   (TOTAL_SIZE / 16) / CELLSIZE,
  133. #else
  134.   STACK_SIZE            /* stack size in cells */
  135.   ? STACK_SIZE
  136.     : (TOTAL_SIZE / 8) / CELLSIZE,
  137.   FLT_STACK_SIZE        /* floating point stack size in items */
  138.   ? FLT_STACK_SIZE
  139.     : (TOTAL_SIZE / 16) / DFLOATSIZE,
  140.   RET_STACK_SIZE        /* return stack size in items */
  141.   ? RET_STACK_SIZE
  142.     : (TOTAL_SIZE / 16) / CELLSIZE,
  143. #endif
  144.  
  145.   MAX_FILES,            /* max_files */
  146.   POCKETS,            /* pockets */
  147.   NULL,                /* save_dict */
  148.   NULL,                /* load_dict */
  149.   PFERC_FILE,            /* pferc_file */
  150.   DEFAULT_BLKFILE,        /* block_file */
  151.   NULL,                /* include_file */
  152.   INC_PATHS,            /* incpath */
  153.   INC_EXTENSIONS,        /* incext */
  154.   BLK_PATHS,            /* blkpath */
  155.   BLK_EXTENSIONS,        /* blkext */
  156.   EDITOR            /* preferred text file editor */
  157. };
  158.  
  159. static void
  160. howto (void)
  161. {
  162.   fprintf (stderr,
  163.        "%s\n%s\n"
  164.        "Usage: %s [-bcdefhklrsv] [file]\n"
  165.        "  -b FILE" "\tuse FILE as block device\n"
  166.        "  -c\t" "\tturn on CAPS lock [%s]\n"
  167.        "  -d FILE" "\treload dictionary image from FILE\n"
  168.        "  -D FILE" "\tbuild dictionary image and exit\n"
  169.        "  -e NAME" "\tNAME of preferred ASCII text editor [%s]\n"
  170.        "  -E\t" "\tallow input of floating point numbers [%s]\n"
  171.        "  -fN\t" "\tmaximum N simultaneously open files [%d]\n"
  172.        "  -F\t" "\tconvert file names to lower case [%s]\n"
  173.        "  -h\t" "\tdisplay this message and exit\n"
  174.        "  -k SIZE" "\tSIZE of system in KBytes [%d K]\n"
  175.        "  -l\t" "\tallow input of lower case words [%s]\n"
  176.        "  -L\t" "\tdisplay license\n"
  177.        "  -p SIZE" "\tSIZE of floating point stack in items [%d]\n"
  178.        "  -PN" "\tnumber of pockets for S\" [%d]\n"
  179.        "  -q\t" "\tsuppress signon message\n"
  180.        "  -r SIZE" "\tSIZE of return stack in cells [%d]\n"
  181.        "  -s SIZE" "\tSIZE of stack in cells [%d]\n"
  182.        "  -t CxR" "\ttext screen has C [%d] columns and R [%d] rows\n"
  183.        "  -v\t" "\tverbose\n"
  184.        "  -W\t" "\tdisplay warranty. Of course: Absolutely none.\n"
  185.        "Turn option off by appending \"-\" to the letter.\n"
  186.        "The given file is loaded initially.\n\n",
  187.        version_string, copyright_string,
  188.        _argv[0],
  189.        option.caps_on ? "ON" : "OFF",
  190.        option.editor,
  191.        option.float_input ? "ON" : "OFF",
  192.        (int) option.max_files,
  193.        option.lower_case_fn ? "ON" : "OFF",
  194.        (int) option.total_size >> 10,
  195.        option.lower_case_on ? "ON" : "OFF",
  196.        (int) option.flt_stack_size,
  197.        (int) option.pockets,
  198.        (int) option.ret_stack_size,
  199.        (int) option.stack_size,
  200.        (int) option.cols, (int) option.rows);
  201.   eXit (1);
  202. }
  203.  
  204. static void
  205. get_options (int argc, char *argv[])
  206. {
  207.   char env_opt[0x400];        /* options from environment variable */
  208.   int i, optc, flag;        /* count of all options */
  209.   char *optv[100];        /* values of all options */
  210.   char opt, *t, *val;
  211.  
  212.   /*
  213.    * get special options from environment variables:
  214.    */
  215.   if ((t = getenv ("PFEINCLUDE")) != NULL)
  216.     option.incpaths = strdup (t),
  217.       option.blkpaths = strdup (t);
  218.   if ((t = getenv ("EDITOR")) != NULL)
  219.     option.editor = strdup (t);
  220.  
  221.   /*
  222.    * merge options from environment variable with those from command line:
  223.    */
  224.   optc = 0;
  225.   if ((t = getenv ("PFEOPTIONS")) != NULL)
  226.     {
  227.       strcpy (env_opt, t);
  228.       t = strtok (env_opt, " ");
  229.       do
  230.     {
  231.       optv[optc++] = t;
  232.       t = strtok (NULL, " ");
  233.     }
  234.       while (t);
  235.     }
  236.   app_argc = optc;
  237.   for (i = 1; i < argc; i++)
  238.     optv[optc++] = argv[i];
  239.  
  240.   /*
  241.    * process options:
  242.    */
  243.   for (i = 0; i < optc; i++)
  244.     {
  245.       t = optv[i];
  246.       if (*t != '-')
  247.     break;
  248.       opt = *++t;
  249.       /*
  250.        * Simple flag options can be -x or -x- to turn them off:
  251.        */
  252.       flag = t[1] != '-';
  253.       switch (opt)
  254.     {
  255.     /* *INDENT-OFF* */
  256.     case 'c': option.caps_on = flag;    continue;
  257.     case 'l': option.lower_case_on = flag;    continue;
  258.     case 'F': option.lower_case_fn = flag;    continue;
  259.     case 'E': option.float_input = flag;    continue;
  260.     case 'L': option.license = flag;    continue;
  261.     case 'W': option.warranty = flag;    continue;
  262.     case 'q': option.quiet = flag;        continue;
  263.     case 'v': option.verbose = flag;    continue;
  264.     case 'B': option.debug = flag;        continue;
  265.     /* *INDENT-ON* */
  266.     }
  267.       /*
  268.        * Other options have values either following immediately after
  269.        * the option letter or as next command line argument:
  270.        */
  271.       if (*++t)
  272.     val = t;
  273.       else if (i == optc - 1)
  274.     val = NULL;
  275.       else
  276.     val = optv[++i];
  277.       switch (opt)
  278.     {
  279.     /* *INDENT-OFF* */
  280.     default:
  281.     case 'h': howto ();                continue;
  282.     case 'b': option.block_file = val;        continue;
  283.     case 'D': option.save_dict = val;        continue;
  284.     case 'd': option.load_dict = val;        continue;
  285.     case 'e': option.editor = val;            continue;
  286.     case 'k': option.total_size = atoi (val) << 10;    continue;
  287.     case 'p': option.flt_stack_size = atoi (val);    continue;
  288.     case 'P': option.pockets = atoi (val);        continue;
  289.     case 'r': option.ret_stack_size = atoi (val);    continue;
  290.     case 's': option.stack_size = atoi (val);    continue;
  291.     /* *INDENT-ON* */
  292.     case 'f':
  293.       option.max_files = atoi (val);
  294.       if (option.max_files < 4)
  295.         option.max_files = 4;
  296.       continue;
  297.     case 't':
  298.       if (sscanf (val, "%dx%d", &option.cols, &option.rows) != 2)
  299.         option.cols = TEXT_COLS, option.rows = TEXT_ROWS;
  300.       continue;
  301.     case 'I':
  302.       t = option.incpaths + strlen (option.incpaths);
  303.       *t++ = PATH_DELIMITER;
  304.       strcpy (t, val);
  305.       t = option.blkpaths + strlen (option.incpaths);
  306.       *t++ = PATH_DELIMITER;
  307.       strcpy (t, val);
  308.       continue;
  309.     }
  310.     }
  311.   if (i < optc)
  312.     option.include_file = optv[i++];
  313.  
  314.   /*
  315.    * Register options starting from included file name in app_argc/v:
  316.    */
  317.   app_argc = i - app_argc;
  318.   app_argv = &argv[app_argc];
  319.   app_argc = argc - app_argc;
  320. }
  321.  
  322. /************************************************************************/
  323. /* Initialize memory map:                                               */
  324. /************************************************************************/
  325.  
  326. struct lined accept_lined;
  327.  
  328. static void
  329. init_accept_lined (void)
  330. {
  331.   extern void accept_executes_xt (int);
  332.   static void (*exec[10]) (int) =
  333.   {
  334.     accept_executes_xt, accept_executes_xt, accept_executes_xt,
  335.     accept_executes_xt, accept_executes_xt, accept_executes_xt,
  336.     accept_executes_xt, accept_executes_xt, accept_executes_xt,
  337.     accept_executes_xt,
  338.   };
  339.  
  340.   memset (&accept_lined, 0, sizeof accept_lined);
  341.   accept_lined.history = membot.history;
  342.   accept_lined.history_max = memsiz.history;
  343.   accept_lined.complete = complete_dictionary;
  344.   accept_lined.executes = exec;
  345.   accept_lined.caps = option.caps_on != 0;
  346. }
  347.  
  348. static void
  349. allocate (void *p, uCell size)
  350. /* Allocates all memory areas in a continuous buffer at p with given size. */
  351. {
  352.   void *q = (char *) p + size;
  353.   typedef char pock_t[POCKET_SIZE];
  354.   /* *INDENT-OFF* */
  355. #define ALLOC(TYPE,ALIGN,AREA,SIZE)        \
  356.   (                        \
  357.    memtop.AREA = (TYPE *) ((size_t)q & ~((size_t)(ALIGN) - 1)), \
  358.    memsiz.AREA = (SIZE) * sizeof (TYPE),    \
  359.    ADD (q, -(SIZE) * sizeof (TYPE)),        \
  360.    membot.AREA = (TYPE *)q            \
  361.   )
  362.  
  363.   ALLOC (File,    CELL_ALIGN,    files,    option.max_files + 3);
  364.   ALLOC (char,    1,        history, HISTORY_SIZE);
  365.   ALLOC (char,    1,        tib,    TIB_SIZE);
  366.   ALLOC (pock_t, 1,        pocket,    option.pockets);
  367.   ALLOC (Xt *,    CELL_ALIGN,    rstack,    option.ret_stack_size);
  368.   ALLOC (double, DFLOAT_ALIGN,    fstack,    option.flt_stack_size);
  369.   ALLOC (Cell,    CELL_ALIGN,    stack,    option.stack_size);
  370. #undef ALLOC
  371.   /* *INDENT-ON* */
  372.  
  373.   if ((char *) q < (char *) p + MIN_PAD + MIN_HOLD + 0x4000)
  374.     fatal ("impossible memory map");
  375.   membot.dict = (Byte *) p;
  376.   memtop.dict = (Byte *) q;
  377.   memsiz.dict = (char *) q - (char *) p;
  378.   init_accept_lined ();
  379. }
  380.  
  381. /************************************************************************/
  382. /* Here's main()                                                        */
  383. /************************************************************************/
  384.  
  385. int
  386. main (int argc, char *argv[])
  387. {
  388.   _argc = argc;            /* pass arguments to Forth words */
  389.   _argv = argv;            /* ARGC and ARGV in misc.c */
  390.  
  391. #ifdef HAVE_LOCALE_H
  392.   setlocale (LC_ALL, "C");
  393. #endif
  394. #if defined EMX
  395.   _control87 (EM_DENORMAL | EM_INEXACT, MCW_EM);
  396. #endif
  397.   if (setjmp (abort_dest) || setjmp (quit_dest))
  398.     fatal ("Error setting up");
  399.  
  400.   get_options (argc, argv);
  401.   install_signal_handlers ();
  402. #if !defined __WATCOMC__
  403.   if (!isatty (STDIN_FILENO))
  404.     option.stdio = 1;
  405.   else
  406. #endif
  407.     {
  408.       option.stdio = 0;
  409.       if (!prepare_terminal ())
  410.     {
  411.       if (!option.quiet)
  412.         fputs ("[unknown terminal, "
  413. #if defined ASSUME_VT100
  414.            "assuming vt100"
  415. #else
  416.            "running in canonical mode"
  417. #endif
  418.            "]\n", stderr);
  419. #if !defined ASSUME_VT100
  420.       option.canonical = 1;
  421. #endif
  422.     }
  423.       interactive_terminal ();
  424.       atexit (system_terminal);
  425.     }
  426.   if (!option.quiet)
  427.     {
  428.       outs (version_string);
  429.       outs (copyright_string);
  430.       if (!option.license || !option.warranty)
  431.     outs (" Please enter LICENSE and WARRANTY.");
  432.       if (option.license)
  433.     outs (license_string);
  434.       if (option.warranty)
  435.     outs (warranty_string);
  436.       outs ("\n\nTo quit say BYE."
  437.         "\n\nHi there, enjoy Forth!\n");
  438.     }
  439.   if (rows == 0)
  440.     rows = option.rows;
  441.   if (cols == 0)
  442.     cols = option.cols;
  443.   allocate ((char *) getmem ((size_t) option.total_size),
  444.         option.total_size);
  445.  
  446.   initialize_system ();
  447.  
  448.   /* If a dictionary image was built and saved, quit now: */
  449.   if (option.save_dict)
  450.     return 0;
  451.  
  452.   /* If running in a pipe, process commands from stdin: */
  453.   if (option.stdio)
  454.     {
  455.       include_file (sys.stdIn);
  456.       return 0;
  457.     }
  458.  
  459.   /* If it's a turnkey-application, start it: */
  460.   if (APPLICATION)
  461.     {
  462.       run_forth (APPLICATION);
  463.       return 0;
  464.     }
  465.   if (option.verbose)
  466.     dot_memory_ ();
  467.   do_abort ();
  468.   return 0;
  469. }
  470.